﻿// 3719. 畅通工程.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>

using namespace std;
/*
https://www.acwing.com/problem/content/3722/

某省调查城镇交通状况，得到现有城镇道路统计表，表中列出了每条道路直接连通的城镇。

省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通
（但不一定有直接的道路相连，只要互相间接通过道路可达即可）。

问最少还需要建设多少条道路？

输入格式
第 1行给出两个正整数，分别是城镇数目 N和道路数目 M。

随后的 M行对应 M条道路，每行给出一对正整数，分别是该条道路直接连通的两个城镇的编号。

为简单起见，城镇从 1到 N编号。

注意:两个城市之间可以有多条道路相通。

也就是说

3 3
1 2
1 2
2 1
这种输入也是合法的

输出格式
输出一个整数，表示最少还需要建设的道路数目。

数据范围
1≤N≤1000
,
1≤M≤10000
输入样例：
4 2
1 3
4 3
输出样例：
1
*/

const int N = 1010;
int f[N], idx;
int n, m;
int hashA[N];

void init() {
	for (int i = 0; i < N; i++) {
		f[i] = i;
	}
}

int find(int x) {
	if (x != f[x]) { f[x] = find(f[x]); }
	return f[x];
}

void merge(int a, int b) {
	a = find(a); b = find(b);
	f[a] = b;
}

int main()
{
	cin >> n >> m;
	init();
	for (int i = 0; i < m; i++) {
		int a, b; cin >> a >> b;
		merge(a, b);
	}
	int total = 0;
	for (int i = 1; i <= n; i++) {
		int a = find(i);
		if (hashA[a] == 0) {
			total++;
			hashA[a] = 1;
		}
	}

	cout << total - 1 << endl;


	return 0;
}

